// upload.js 修改内容
import axios from 'axios'
import { getToken } from '@/utils/auth'
// import service from "@/utils/request"
class FileUploadUtil {
    constructor() {
        // 初始化状态
        this.resetState();
        this.filesInfo = [];
    }

    // 重置状态
    resetState() {
        this.fileData = {
            file : null,
            fileName : '',
            fileSize : 0,
            fileType : '',
            fileExtension : '',
            content : null,
            previewUrl : null,
            loading : false,
            progress : 0,
            error : '',
            reader : null,
            skuId : 99,
        }
    }

    /**
     * 处理文件上传
     * @param {File} file - 要上传的文件
     * @param {Object} options - 配置选项
     * @param {number} options.maxSize - 最大文件大小(字节)
     * @param {Array} options.acceptTypes - 允许的文件类型数组，如['image/*', 'video/*']
     */
    handleFileUpload(file, options = {}) {
        // 重置之前的状态
        this.resetState();

        // 验证文件是否存在
        if (!file) {
            this.error = '未选择文件';
            return;
        }

        // 保存文件信息
        this.fileData.file = file;
        this.fileData.fileName = file.name;
        this.fileData.fileSize = file.size;
        this.fileData.fileType = file.type;
        this.fileData.skuId = 99;
        // this.files.push(file);
        // 获取文件扩展名
        const lastDotIndex = file.name.lastIndexOf('.');
        this.fileData.fileExtension = lastDotIndex > 0
            ? file.name.substring(lastDotIndex + 1).toLowerCase()
            : '';

        // 验证文件类型
        if (options.acceptTypes && !this.isTypeAllowed(options.acceptTypes)) {
            this.error = `不支持的文件类型，允许的类型: ${this.formatAcceptTypes(options.acceptTypes)}`;
            return;
        }

        // 验证文件大小
        if (options.maxSize && file.size > options.maxSize) {
            this.error = `文件过大，最大支持 ${this.fileData.formatFileSize(options.maxSize)}`;
            return;
        }

        // 根据文件类型处理预览和读取
        this.processFile();
        this.filesInfo.push(this.fileData);
    }

    /**
     * 修改：增加file参数，支持验证指定文件
     * 检查文件类型是否被允许
     * @param {Array} acceptTypes - 允许的文件类型数组
     * @param {File} file - 可选，要检查的文件，默认使用当前文件
     * @returns {boolean} 是否允许
     */
    isTypeAllowed(acceptTypes, file = this.file) {
        if (!file) return false;

        // 检查是否是通配符类型
        if (acceptTypes.includes('*/*')) return true;

        // 检查具体类型
        for (const type of acceptTypes) {
            // 处理通配符类型如 'image/*'
            if (type.endsWith('*')) {
                const baseType = type.split('/')[0];
                if (file.type.startsWith(baseType)) {
                    return true;
                }
            }
            // 处理具体类型如 'image/jpeg'
            else if (file.type === type) {
                return true;
            }
            // 处理扩展名如 '.pdf'
            else if (type.startsWith('.') && this.getFileExtension(file) === type.substring(1)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 修改：添加获取文件扩展名的工具方法
     * @param {File} file - 文件对象
     * @returns {string} 扩展名
     */
    getFileExtension(file) {
        const lastDotIndex = file.name.lastIndexOf('.');
        return lastDotIndex > 0
            ? file.name.substring(lastDotIndex + 1).toLowerCase()
            : '';
    }

    /**
     * 格式化允许的文件类型显示
     * @param {Array} acceptTypes - 允许的文件类型数组
     * @returns {string} 格式化后的字符串
     */
    formatAcceptTypes(acceptTypes) {
        return acceptTypes.map(type => {
            if (type === '*/*') return '所有文件';
            if (type.endsWith('*')) return type.split('/')[0] + '文件';
            if (type.startsWith('.')) return type.toUpperCase() + '文件';
            return type.split('/')[1] + '文件';
        }).join('、');
    }

    /**
     * 处理文件读取和预览
     */
    processFile() {
        // 创建FileReader实例
        this.reader = new FileReader();

        // 绑定事件处理函数
        this.reader.onabort = this.handleAbort.bind(this);

        // 根据文件类型选择合适的读取方式
        if (this.isImage()) {
            // 图片文件，创建预览URL
            this.fileData.previewUrl = URL.createObjectURL(this.fileData.file);
            // 同时读取为DataURL
            this.reader.readAsDataURL(this.file);
        } else if (this.isVideo()) {
            // 视频文件，创建预览URL
            this.fileData.previewUrl = URL.createObjectURL(this.fileData.file);
            // 读取为ArrayBuffer
            this.reader.readAsArrayBuffer(this.fileData.file);
        } else if (this.isTextFile()) {
            // 文本文件，读取为文本
            this.reader.readAsText(this.fileData.file);
        } else {
            // 其他文件，读取为ArrayBuffer
            this.reader.readAsArrayBuffer(this.fileData.file);
        }
    }

    isImage() {
        return this.fileType.startsWith('image/');
    }
    isVideo() {
        return this.fileType.startsWith('video/');
    }
    isTextFile() {
        const textExtensions = ['txt', 'csv', 'html', 'css', 'js', 'json', 'xml', 'md'];
        return this.fileType.startsWith('text/') || textExtensions.includes(this.fileExtension);
    }
    isDocument() {
        const docExtensions = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx'];
        return docExtensions.includes(this.fileExtension);
    }
    removeFile(index) {
        this.filesInfo.splice(index, 1);
    }
    /**
     * 释放预览URL资源
     */
    revokePreviewUrl(item) {
        if (item.previewUrl) {
            URL.revokeObjectURL(item.previewUrl);
            item.previewUrl = null;
        }
    }

    /**
     * 上传文件到服务器
     * @param {string} url - 服务器上传地址
     * @param {Object} additionalData - 额外的表单数据
     * @returns {Promise} 返回上传结果的Promise
     */
    uploadToServer(url, additionalData = {}) {
        return new Promise((resolve, reject) => {
            // 检查是否有文件可上传
            if (!this.files || this.files.length === 0) {
                this.error = '没有可上传的文件';
                reject(new Error(this.error));
                return;
            }

            // 初始化上传状态
            this.loading = true;
            this.error = '';

            // 创建表单数据对象
            const formData = new FormData();

            formData.append('files', files);
            formData.append("skuId", additionalData.skuId ? additionalData.skuId : this.skuId);

            // 添加额外数据
            Object.keys(additionalData).forEach(key => {
                formData.append(key, additionalData[key]);
            });

            // 使用request.js中的service发送请求
            axios.post(url, formData, {
                // 监听上传进度
                onUploadProgress: (e) => {
                    if (e.lengthComputable) {
                        const progress = (e.loaded / e.total) * 100;
                        console.log(`文件上传进度: ${progress.toFixed(2)}%`);
                    }
                },
                // 注意：axios会自动为FormData设置正确的Content-Type
                // 不需要手动设置multipart/form-data，否则可能导致边界缺失问题
                headers: {
                    'Content-Type': 'multipart/form-data',
                    'Authorization': 'Bearer ' + getToken()
                }
            })
                .then(response => {
                    this.loading = false;
                    resolve(response);
                })
                .catch(error => {
                    this.loading = false;

                    if (error.response) {
                        this.error = `上传失败: 服务器返回状态码 ${error.response.status}`;
                    } else if (error.request) {
                        this.error = '上传失败: 网络错误';
                    } else if (error.message) {
                        this.error = `上传失败: ${error.message}`;
                    } else {
                        this.error = '上传失败: 发生未知错误';
                    }

                    reject(new Error(this.error));
                });
        });
    }
    /**
     * 格式化文件大小显示
     * @param {number} bytes - 文件大小(字节)
     * @returns {string} 格式化后的大小字符串
     */
    formatFileSize(bytes) {
        if (bytes === 0) return '0 Bytes';
        const k = 1024;
        const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
        const i = Math.floor(Math.log(bytes) / Math.log(k));
        return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    }
}

export default FileUploadUtil;